/*
@Time : 2020/12/29 10:28 上午
@Author : chenle
@File : lego
@Software: GoLand
*/
package lego

import (
	"log"
	"net/http"
)

type Lego struct {
	Router *Router
	Engine *Engine
}

var app *Lego

// 初始化全局应用实例
func New() *Lego {
	app = &Lego{
		Engine: &Engine{
			MaxMultipartMemory: defaultMultipartMemory,
			BeforeFilters:      Events{},
			AfterFilters:       Events{},
		},
		Router: NewRouter(),
	}
	app.loadConf()
	app.initLogger()
	return app
}

func (l *Lego) Run() {
	log.Fatal(http.ListenAndServe(":"+l.Engine.Config.HttpPort, l))
}

func (l *Lego) RunTsl(certFile, keyFile string) {
	log.Fatal(http.ListenAndServeTLS(":"+l.Engine.Config.HttpPort, certFile, keyFile, l))
}

// 开启 mysql
func (l *Lego) EnableMysql(values ...interface{}) *Lego {
	if l.Engine.Config.UserGorm2 {
		l.initDatabase2_0(values...)
	}
	l.initDataBase(values...)
	return l
}

func (l *Lego) HttpPort() string {
	return l.Engine.Config.HttpPort
}

// 开启 redis
func (l *Lego) EnableRedis() *Lego {
	l.initCache()
	return l
}

func (l *Lego) ServeHTTP(w http.ResponseWriter, req *http.Request) {

	l.Router.ServeHTTP(w, req)
}

func (l *Lego) Handler(method string, path string, handler http.Handler) {
	l.Router.Handler(method, path, handler)
}

func (l *Lego) GET(path string, events ...Event) {
	l.Router.GET(path, events)
}

func (l *Lego) POST(path string, events ...Event) {
	l.Router.POST(path, events)
}

func (l *Lego) DELETE(path string, events ...Event) {
	l.Router.DELETE(path, events)
}

func (l *Lego) PUT(path string, events ...Event) {
	l.Router.PUT(path, events)
}

func (l *Lego) OPTIONS(path string, events ...Event) {
	l.Router.OPTIONS(path, events)
}

func (l *Lego) PATCH(path string, events ...Event) {
	l.Router.PATCH(path, events)
}

func (l *Lego) HEAD(path string, events ...Event) {
	l.Router.HEAD(path, events)
}

// 注册数据库表结构
func (l *Lego) MigrateModels(v ...interface{}) *Lego {
	if l.Engine.Config.UserGorm2 {
		l.Engine.DB2.AutoMigrate(v...)
	} else {
		l.Engine.DB.AutoMigrate(v...)
	}

	return l
}

// 添加前置拦截
func (l *Lego) AddBeforeFilters(events ...Event) *Lego {
	l.Engine.BeforeFilters = append(l.Engine.BeforeFilters, events...)
	return l
}

// 添加后置拦截
func (l *Lego) AddAfterFilters(events ...Event) *Lego {
	l.Engine.AfterFilters = append(l.Engine.AfterFilters, events...)
	return l
}

// 开启cors跨域
func (l *Lego) EnableCors(config CorsConf) *Lego {
	l.Engine.EnabledCors = true
	l.AddBeforeFilters(NewCors(config))
	return l
}

func (l *Lego) OpenCors(headers ...string) {
	l.Engine.OpenCors = true
	if headers != nil && len(headers) > 0 {
		l.Engine.corsHeaders = headers
	}
	//l.AddBeforeFilters(func(c *Context) {
	//	origin := c.GetHeader("Origin")
	//	if origin != "" {
	//		c.Header("Access-Control-Allow-Origin", origin)
	//	} else {
	//		c.Header("Access-Control-Allow-Origin", "*")
	//	}
	//
	//	c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, PUT, HEAD")
	//	c.Header("Access-Control-Allow-Credentials", "true")
	//	c.Header("Access-Control-Max-Age", "1728000")
	//	if len(headers) > 0 {
	//		c.Header("Access-Control-Allow-Headers", strings.Join(headers, ","))
	//	} else {
	//		c.Header("Access-Control-Allow-Headers", "Accept, Accept-Encoding, X-CSRF-Token, Authorization, Origin, Content-Length, Content-Type, token, Userid, Access-Control-Allow-Origin, dir, title, number")
	//	}
	//
	//	if c.Request.Method == http.MethodOptions {
	//		c.AbortWithStatus(204)
	//	}
	//})
}

type GroupRouter struct {
	l      *Lego
	events Events
	prefix string
}

func (l *Lego) Group(path string, events ...Event) *GroupRouter {
	return &GroupRouter{
		l:      l,
		events: events,
		prefix: path,
	}
}

func (g *GroupRouter) combineEvents(events Events) Events {
	final := make([]Event, 0)
	final = append(final, g.events...)
	final = append(final, events...)
	return final
}

func (g *GroupRouter) GET(path string, events ...Event) {

	g.l.GET(g.prefix+path, g.combineEvents(events)...)
}

func (g *GroupRouter) POST(path string, events ...Event) {
	g.l.POST(g.prefix+path, g.combineEvents(events)...)
}

func (g *GroupRouter) PUT(path string, events ...Event) {
	g.l.PUT(g.prefix+path, g.combineEvents(events)...)
}

func (g *GroupRouter) DELETE(path string, events ...Event) {
	g.l.DELETE(g.prefix+path, g.combineEvents(events)...)
}

func (g *GroupRouter) HEAD(path string, events ...Event) {
	g.l.HEAD(g.prefix+path, g.combineEvents(events)...)
}

func (g *GroupRouter) OPTIONS(path string, events ...Event) {
	g.l.OPTIONS(g.prefix+path, g.combineEvents(events)...)
}

func (g *GroupRouter) PATCH(path string, events ...Event) {
	g.l.PATCH(g.prefix+path, g.combineEvents(events)...)
}
